package com.ra.order.rental;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.ListOrderedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.da.landlord.DaAgreement;
import com.da.landlord.DaChargeBillRecord;
import com.da.landlord.DaChargeItem;
import com.da.landlord.DaFeeRule;
import com.da.landlord.DaRoom;
import com.da.landlord.DaSuite;
import com.da.landlord.PaidNoticeService;
import com.espirit.eap.sa.LoginUser;
import com.espirit.eap.sa.LoginUserService;
import com.espirit.eap.util.Functions;
import com.espirit.eap.util.ImageUtils;
import com.espirit.weixin.core.WeixinConfig;
import com.espirit.weixin.core.WeixinUtil;
import com.googlecode.cswish.Config;
import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.model.Reference;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.FreemarkerResult;
import com.googlecode.cswish.struts.ServletRedirectResult;
import com.googlecode.cswish.struts.spring.GenericService;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.googlecode.cswish.util.bean.ModelUtil;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.Result;
import com.ra.coupon.UserCoupon;
import com.ra.external.FinanceStatementService;
import com.ra.external.WeixinUserService;
import com.ra.landlord.Agreement;
import com.ra.landlord.Building;
import com.ra.landlord.Fee;
import com.ra.landlord.FeeAddition;
import com.ra.landlord.FeeAdditionRecord;
import com.ra.landlord.FeeAdditionService;
import com.ra.landlord.FeeRecord;
import com.ra.landlord.FeeRecordService;
import com.ra.landlord.FeeRule;
import com.ra.landlord.FeeRuleCfg;
import com.ra.landlord.FeeRuleCfgCalc;
import com.ra.landlord.FeeRuleCfgDesc;
import com.ra.landlord.FeeService;
import com.ra.landlord.LandlordOwnerUser;
import com.ra.landlord.LandlordPurchaseInfoService;
import com.ra.landlord.LandlordUser;
import com.ra.landlord.LandlordUserService;
import com.ra.landlord.Meter;
import com.ra.landlord.Room;
import com.ra.landlord.RoomAttachment;
import com.ra.landlord.RoomService;
import com.ra.landlord.TenantUser;
import com.ra.landlord.TenantUserService;
import com.ra.landlord.ValidAgreement;
import com.ra.landlord.constant.FeeRuleType;
import com.ra.landlord.constant.LandlordConstant;
import com.ra.landlord.vo.AgreementVO;
import com.ra.landlord.vo.OrderItemsVO;
import com.ra.landlord.vo.OrderVO;
import com.ra.order.BatchTransRecord;
import com.ra.order.OrderUtil;
import com.ra.order.PayOrder;
import com.ra.pay.PaymentRecord;
import com.ra.pay.alipay.AlipayConfig;
import com.ra.pay.alipay.AlipayNotify;
import com.ra.pay.alipay.AlipayService;
import com.ra.pay.alipay.AlipayUtil;
import com.ra.pay.weixin.EnterpriseTransfer;
import com.ra.pay.weixin.GetWxOrderno;
import com.ra.pay.weixin.RequestHandler;
import com.ra.pay.weixin.WeixinGoods;
import com.ra.pay.weixin.WeixinPay_bakService;
import com.ra.statis.LandlordEstimation;
import com.ra.statis.LandlordEstimationService;
import com.ra.util.Address;
import com.ra.util.CommonService;
import com.ra.util.DateTimeUtil;
import com.ra.util.RaConstant;
import com.ra.util.SmsLog;
import com.ra.util.SmsService;
import com.ra.weixin.WeixinUser;

@Service
public class RentalOrderService {
	
	private static final Log logger = LogFactory.getLog(AlipayUtil.class);

	@Resource
	private GenericService genericService;
	
	@Resource
	private AlipayService alipayService;
	
	@Resource
	private LoginUserService loginUserService;
	
	@Resource
	private ObjectFactory objectFactory;
	
	@Resource
	private WeixinUserService weixinUserService;
	
	@PersistenceContext(unitName = "espirit")
	protected EntityManager em;
	
	@Resource
	private SmsService smsService;
	
	@Resource
	private FeeAdditionService feeAdditionService;
	
	@Resource
	private LandlordUserService landlordUserService;
	
	@Resource
	private LandlordPurchaseInfoService landlordPurchaseService;
	
	@Resource
	private FeeService feeService;
	
	@Resource
	private Functions functions;
	
	@Resource 
	private WeixinPay_bakService weixinPayService;
	
	@Resource
	private RoomService roomService;
	
	@Resource
	private FeeRecordService feeRecordService;
	
	@Resource
	private TenantUserService tenantUserService;
	
	@Resource
	private FinanceStatementService financeStatementService;
	
	@Resource
	private WeixinUtil weixinUtil;
	
	@Resource
	private PaidNoticeService paidNoticeService;
	
	@Resource
	private CommonService commonService;
	
	@Resource
	private LandlordEstimationService landlordEstimationService;
	
	public <T> PageInfo<T> search(T model, int start, int limit, String sort, String dir, boolean oldSearch, boolean fromMenu, Reference<QLInfo> qlInfoRef) {
		if (fromMenu) {
			ModelUtil.setSimpleProperty(model, "orderState", RentalOrder.ORDER_STATE_PAYMENTED);
		}
		
    	return genericService.search(model, start, limit, sort, dir, oldSearch, qlInfoRef, null, true, false);
    }
	
	/**
	 * 百万活动，租客在线交租，即给房东生成一笔补贴订单
	 * 参数必须设置model.setFeeRecord()、model.setTotalFee()、model.setOrderDec
	 * 
	 * @param model
	 * @return
	 */
	public RentalOrder addRentalOrderOfActivity(RentalOrder model){
		Date date = Calendar.getInstance().getTime();
		model.setCreateTime(new Timestamp(date.getTime()));
		// admin
		LandlordOwnerUser landlordUser = model.getRoom().getLandlordUser();
		model.setCreateUser(landlordUser);
		model.setOrderState(RentalOrder.ORDER_STATE_PAYMENTED);
		// 商品订单号
		String outTradeNo = OrderUtil.getOrderNum();
		model.setOutTradeNo(outTradeNo);
		
		// 订单名称
		String orderName = getOrderName(model.getFeeRecord(), "交租补贴");
		model.setOrderName(orderName);
		
		// 设置房源信息
		model.setRoom(model.getFeeRecord().getRoom());
		
		//补贴类型
		model.setOrderType(RentalOrder.ORDERTYPE_ACTIVITY);
		
		return genericService.add(model);
	}
	
	/**
	 * 非认证房东，交租手续费，额外生成一笔手续费订单
	 * @param model
	 * @return
	 */
	public void addRentalOrderOfPoundage(RentalOrder model) {
		// admin
		LandlordOwnerUser landlordUser = model.getRoom().getLandlordUser();
		
		// 非认真房东手续费
		if (isAddPoundage(landlordUser)) {
			Date date = Calendar.getInstance().getTime();
			model.setCreateTime(new Timestamp(date.getTime()));
			
			model.setCreateUser(landlordUser);
			model.setOrderState(RentalOrder.ORDER_STATE_PAYMENTED);
			// 商品订单号
			String outTradeNo = OrderUtil.getOrderNum();
			model.setOutTradeNo(outTradeNo);
			
			// 将对应订单的订单号设置到当前订单的描述中
			model.setOrderDec(model.getOutTradeNo());
			
			// 订单名称
			String orderName = getOrderName(model.getFeeRecord(), "非认证房东交租手续费");
			model.setOrderName(orderName);
			
			// 设置房源信息
			model.setRoom(model.getFeeRecord().getRoom());
			
			//补贴类型
			model.setOrderType(RentalOrder.ORDERTYPE_POUNDAGE);
			
			BigDecimal totalFee = model.getTotalFee().multiply(new BigDecimal(RentalOrder.POUNDAGE_AMOUNT_RATE));
			totalFee = totalFee.setScale(2, BigDecimal.ROUND_HALF_UP);
			model.setTotalFee(totalFee);
			
			genericService.add(model);
		}
	}
	
	
	@SuppressWarnings("unchecked")
	public void creditCardIntercept(BigDecimal totalFee) {
		LandlordUser landlordUser = landlordUserService.getLandlordOwnerUser();
		landlordUser = genericService.load(LandlordUser.class, landlordUser.getId());
		
		if(landlordUser == null) {
			throw new ApplicationException("对不起，您是无效房东，无法进行网上收租！");
		}
		
		if (isAddPoundage(landlordUser)) { // 非认证房东
			
			// 非认证房东单比订单总额不能超过5000
			BigDecimal compareFee = new BigDecimal("5000.00");
			int compareResult = totalFee.compareTo(compareFee);
			if (compareResult == 1) {
				throw new ApplicationException("对不起，您是未认证房东，单笔订单限额不能超过5000！");
			}

			// 非认证房东单月交易总额不能超过10万
			String ql = "from "
					+ RentalOrder.class.getName()
					+ " a where a.hhzPay is true and a.createTime >= ? and a.createTime <= ? and a.createUser.id = ?";
			List<Object> params = new ArrayList<Object>();
			params.add(DateTimeUtil.getCurrentMonthStartTime());
			params.add(DateTimeUtil.getCurrentMonthEndTime());
			params.add(landlordUser.getId());

			QLInfo objQLInfo = new QLInfo(ql, true, params);

			List<RentalOrder> rentalOrders = genericService.searchByQl(
					objQLInfo, false).getData();
			if (CollectionUtils.isNotEmpty(rentalOrders)) {
				BigDecimal monthTotalFee = new BigDecimal("0.00");
				for (RentalOrder temp : rentalOrders) {
					BigDecimal tmpFee = temp.getTotalFee();
					monthTotalFee = monthTotalFee.add(tmpFee);
					if (monthTotalFee.compareTo(new BigDecimal("100000.00")) == 1) {
						throw new ApplicationException(
								"对不起，您是未认证房东，当月订单总额不能超过100000！");
					}
				}
			}
		}
	}
	
	/**
	  * 新增租金订单信息
	  * 
	  * @param model 订单信息
	  * @param feeRecordStatus 订单状态
	  * @return 订单信息
	  */
	public RentalOrder addRentalOrder(RentalOrder model, Integer feeRecordStatus) {
		LandlordOwnerUser landlordUser = landlordUserService.getLandlordOwnerUser();

		// 网上收租单费用
		BigDecimal totalFee = model.getTotalFee();
		if(totalFee == null) {
			totalFee = model.getFeeRecord().getAmountActual();
			if (totalFee == null) {
				totalFee = model.getFeeRecord().getAmountRecv();
			}
		}
		
		// TODO 防止信用卡恶意套现限制
		if(model.getOrderState() == null || model.getOrderState() == RentalOrder.ORDER_STATE_WAITING_PAYMENT) {
			creditCardIntercept(totalFee);
		}
		

		// 更新费用
		FeeRecord feeRecord = null;
		if (model.getFeeRecord() != null) {
			feeRecord = model.getFeeRecord();
			if (feeRecordStatus == null) {
				feeRecord.setStatus(FeeRecord.FEE_STATUS_RENT_TODO);
				feeRecord = feeRecordService.updateFeeRecord(feeRecord);
			} else {
				feeRecord.setStatus(feeRecordStatus);
				if (model.getOrderState() != null
						&& model.getOrderState() == RentalOrder.ORDER_STATE_CLOSED) {
					feeRecord = feeRecordService.closeFeeRecord(feeRecord,
							FeeRecord.FEE_PAYMODEL_CASH);
				} else {
					FeeRecord newFeeRecord = getNewFeeRecord(feeRecord);
					feeRecord = feeRecordService.updateFeeRecord(newFeeRecord);
				}
			}

			model.setFeeRecord(feeRecord);
		}

		Date date = new Date();
		model.setCreateTime(new Timestamp(date.getTime()));
		model.setCreateUser(landlordUser);
		if (feeRecord != null) {
			model.setTenantUser(feeRecord.getTenantUser());
		}

		// 设置订单状态：等待租客付款
		if (model.getOrderState() == null) {
			model.setOrderState(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
		}

		// 调用工具类获取商品订单号
		String outTradeNo = OrderUtil.getOrderNum();
		model.setOutTradeNo(outTradeNo);
		model.setShowURL("");

		// 订单名称
		String orderName = getOrderName(model.getFeeRecord(), "总费用");
		model.setOrderName(orderName);
		model.setTotalFee(totalFee);

		// 设置房源信息
		model.setRoom(model.getFeeRecord().getRoom());

		// 组装订单描述
		model.setOrderDec(feeRecord.getRemark());

		// 订单类型
		model.setOrderType(RentalOrder.ORDERTYPE_RENTAL);

		return genericService.add(model);
	}
	
	/**
	 * 批量生成租金订单信息
	 * 
	 * @param models 订单集合
	 * @return 订单集合
	 */
	@Rest(type="add")
	public List<RentalOrder> addRentalOrderBatch(List<Integer> feeRecordIds) {
		List<RentalOrder> result = new ArrayList<>();
		for (Integer feeRecordId : feeRecordIds) {
			FeeRecord dbFeeRecord = genericService.load(FeeRecord.class, feeRecordId);
			if (dbFeeRecord != null) {
				FeeRecord newFeeRecord = getNewFeeRecord(dbFeeRecord);
				Agreement agreement = newFeeRecord.getAgreement();
				if (agreement != null) {
					newFeeRecord.setTenantUser(agreement.getTenantUser());
				}
				newFeeRecord.setAmountActual(newFeeRecord.getAmountRecv());
				newFeeRecord.setBalance(new BigDecimal("0.00"));
				RentalOrder rentalOrder = new RentalOrder();
				rentalOrder.setFeeRecord(newFeeRecord);
				rentalOrder.getFeeRecord().getTenantUser();
				rentalOrder.setOrderState(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
				RentalOrder dbRentalOrder = addRentalOrder(rentalOrder, FeeRecord.FEE_STATUS_RENT_TODO);
				if (dbRentalOrder != null) {
					result.add(dbRentalOrder);
				}
			}
		}
		return result;
	}
	
	/**
	 * 获取新的FeeRecord
	 * @param dbFeeRecord
	 * @return
	 */
	private FeeRecord getNewFeeRecord(FeeRecord dbFeeRecord){
		FeeRecord newFeeRecord = new FeeRecord();
		ModelUtil.copy(dbFeeRecord, newFeeRecord, true);
		List<FeeAdditionRecord> feeAdditionRecords = dbFeeRecord.getFeeAdditionRecords();
		List<FeeAdditionRecord> newFeeAdditionRecords = new ArrayList<FeeAdditionRecord>();
		if (feeAdditionRecords != null && feeAdditionRecords.size() > 0) {
			for (FeeAdditionRecord feeAdditionRecord : feeAdditionRecords) {
				FeeAdditionRecord feeAddition = new FeeAdditionRecord();
				ModelUtil.copy(feeAdditionRecord, feeAddition, true);
				feeAddition.setId(null);
				newFeeAdditionRecords.add(feeAddition);
			}
			newFeeRecord.setFeeAdditionRecords(newFeeAdditionRecords);
		}
		return newFeeRecord;
	}
	
	public String getFeeInfoDesc(RentalOrder RentalOrder) {
		FeeRecord feeRecord = RentalOrder.getFeeRecord();
		StringBuffer sb = new StringBuffer();
		sb.append("----费用单据----").append("\n");
		BigDecimal rental = feeRecord.getRental();
		if(rental != null){
			rental = rental.setScale(2,BigDecimal.ROUND_HALF_UP);
		}
		sb.append("*").append(" 房租：" + rental).append("\n");
		List<FeeAdditionRecord> feeAdditions = feeRecord.getFeeAdditionRecords();
		if (feeAdditions != null && feeAdditions.size() > 0) {
			for (int i = 0; i < feeAdditions.size(); i++) {
				FeeAdditionRecord feeAddition = feeAdditions.get(i);
				FeeRuleCfgDesc feeRuleCfgDesc = feeAddition.getFeeRuleCfg()
						.getFeeRuleCfgDesc();
				
				if (feeRuleCfgDesc != null) {
					
					BigDecimal price = feeAddition.getPriceActual();
					if(price == null){
						price = feeAddition.getPriceRecv();
					}
					
					String strPrice = "0.00";
					if( price != null ){
						strPrice = price.setScale(2,BigDecimal.ROUND_HALF_UP).toString();
					}
					
					sb.append("*").append(" ")
							.append(feeRuleCfgDesc.getName()).append(": ")
							.append(strPrice)
							.append("\n");
				}
			}
		}
		return sb.toString();
	}
	
	private String getOrderName(FeeRecord feeRecord, String suf) {
		// 时间段开始
		String dateBeginRecv = feeRecord.getDateBeginRecv();
		
		// 时间段结束
		String dateEndRecv = feeRecord.getDateEndRecv();
		
		dateBeginRecv = DateTimeUtil.formatStringDate(dateBeginRecv, DateTimeUtil.ISO_DATE_FORMAT);
		dateEndRecv = DateTimeUtil.formatStringDate(dateEndRecv, DateTimeUtil.ISO_DATE_FORMAT);
		
		String orderName = feeRecord.getRoom().getName() 
				+ "(" +dateBeginRecv + "~" + dateEndRecv + ")" + suf;
		return orderName;
	}
	
	
	public List<RentalOrder> getOrderStateShow(List<RentalOrder> RentalOrders) {
		String orderStateShow = null;
		for(RentalOrder order : RentalOrders) {
			int state = order.getOrderState();
			switch (state) {
			case RentalOrder.ORDER_STATE_WAITING_PAYMENT:
				orderStateShow = "待支付";
				break;
			case RentalOrder.ORDER_STATE_PAYING:
				orderStateShow = "支付中";
				break;
			case RentalOrder.ORDER_STATE_PAYMENTED:
				orderStateShow = "转账中";
				break;
			case RentalOrder.ORDER_STATE_SUCCESS:
				orderStateShow = "交租成功";
				break;
			case RentalOrder.ORDER_STATE_CLOSED:
				orderStateShow = "已关闭";
				break;
			default:
				break;
			}
			order.setOrderStateShow(orderStateShow);
		}
		return RentalOrders;
	}
	
	/**
	 * 订单提交，支付
	 * @param model
	 * @return 成功标识 1：成功，0：失败
	 */
	public Result rentalOrderSubmit(RentalOrder model) {
		// 1.判断支付类型，调用对应支付接口
		String  resultMeg = null;
		Result result = null;
		PayOrder payOrder = new PayOrder();
		switch (model.getPaymentRecord().getPayType()) {
			case PaymentRecord.PAY_TYPE_ALIPAY:
				ModelUtil.copy(model, payOrder, true);
				// 支付宝支付
				resultMeg = alipayService.alipayOrderSubmit(payOrder, RaConstant.ORDER_TYPE_RENTAL);
				ActionContext.getContext().getValueStack().setValue("resultMeg", resultMeg);
				String path = "/site/ra/pagesGen/ra/rent/roomRetrieval.alipayResult.ftl";
				result = new FreemarkerResult(path);
				objectFactory.autoWireBean(result);
				break;
			case PaymentRecord.PAY_TYPE_WEIXIN:
				// 微信支付
				String openId = weixinUserService.getOpenId();
				WeixinGoods goods = new WeixinGoods();
				
				// 将订单信息赋值给WeixinGoods
				// 订单名称
				goods.setBody(model.getOrderName());
				goods.setOutTradeNo(model.getOutTradeNo());
				goods.setTotalFee(model.getTotalFee().toString());
				weixinPayService.wxPay(goods, openId);
				break;
			case PaymentRecord.PAY_TYPE_BANK:
				// 网银支付
				break;
			default:
				break;
		}

		return result;
	}
	
	/**
	 * 根据FeeRecord查询对应订单信息
	 * @param model
	 * @return 订单详情
	 */
	public RentalOrder readRentalOrderInfo(FeeRecord model) {
		RentalOrder queryModel = new RentalOrder();
		queryModel.setFeeRecord(model);
		queryModel.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		return genericService.searchAll(queryModel).getData(0);
	}
	
	/**
	 * 支付宝批量转账租金订单记录
	 */
	public Result batchTransRendRecords(BatchTransRentalRecord model) {
		Integer payType = null;
		List<RentalOrder> rentalOrders = new ArrayList<RentalOrder>();
		for(RentalOrder rentalOrder : model.getRentalOrders()) {
			RentalOrder queryModel = new RentalOrder();
			queryModel.setId(rentalOrder.getId());
			rentalOrder = genericService.load(queryModel);
			rentalOrders.add(rentalOrder);
			payType = rentalOrder.getPaymentRecord().getPayType();
			if(rentalOrder.getOrderState() != RentalOrder.ORDER_STATE_PAYMENTED) {
				throw new ApplicationException("当前选择转账的订单状态有误");
			}
			if(model.getRentalOrders().size() > 1 && payType == BatchTransRentalRecord.PAY_TYPE_WEIXIN) {
				throw new ApplicationException("微信支付的订单暂不支持批量转账");
			}
		}
		
		model.setRentalOrders(rentalOrders);
		
		String resultMeg = null;
		switch (payType) {
			case BatchTransRentalRecord.PAY_TYPE_ALIPAY:
				resultMeg = this.batchTransByAlipay(model);
				break;
			case BatchTransRentalRecord.PAY_TYPE_WEIXIN:
				resultMeg = this.batchTransByWeixin(model);
				break;
			default:
				break;
		}
		ActionContext.getContext().getValueStack().setValue("resultMeg", resultMeg);
		String path = functions.page("/ra/rent/roomRetrieval.alipayResult.ftl");
		Result result = new FreemarkerResult(path);
		objectFactory.autoWireBean(result);
		return result;
	}
	
	/**
	 * 微信批量转账
	 * @param model
	 * @return 转账结果返回页面
	 */
	private String batchTransByWeixin(BatchTransRentalRecord model) {
		EnterpriseTransfer transfer = new EnterpriseTransfer();
		RentalOrder rentalOrder = model.getRentalOrders().get(0);
		
		// 订单标号
		String outTradeNo = rentalOrder.getOutTradeNo();
		transfer.setPartner_trade_no(outTradeNo);
		transfer.setDesc("微信租金转账");
		// TODO
		WeixinUser user = null;
		LoginUser loginUser = rentalOrder.getFeeRecord().getLandlordUser().getLoginUser();
		WeixinUser queryModel = new WeixinUser();
		queryModel.setLoginUser(loginUser);
		
		if (loginUser != null) {
			user = weixinUserService.getWeixinUser(queryModel);
		}
		if(user == null) {
			throw new ApplicationException("房东还未关注好好租公众号");
		}
		transfer.setOpenid(user.getOpenid());
		
		// 金额转换成分
		String finalmoney = BigDecimal.valueOf(Double.parseDouble(model.getRentalOrders().get(0).getTotalFee().toString()))
				.multiply(new BigDecimal(100)).toString(); 
		transfer.setAmount(finalmoney);
		
		// 转账备注
		Room room = rentalOrder.getRoom();
		transfer.setDesc(room.getName() + "租客：" + "(" + room.getAgreement().getTenantUser().getName() + ")转入￥" + rentalOrder.getTotalFee());
		
		String resultMeg = weixinPayService.wxTransfer(transfer);
		
		// 批次号B+当前时间戳
		model.setBatchNo("B" + OrderUtil.getOrderNum());
		
		// 付款总金额
		model.setBatchFee(model.getRentalOrders().get(0).getTotalFee());
		
		WeixinConfig weixinConfig = weixinUtil.getWeixinConfig();
		
		// 付款帐号
		model.setAccountEmail(weixinConfig.getAppId());
		
		// 付款账户名
		model.setAccountName(weixinConfig.getSiteName());
		
		// 付款当天日期
		Calendar now = Calendar.getInstance();
		int year = now.get(Calendar.YEAR);
		int month = now.get(Calendar.MONTH) + 1;
		int day = now.get(Calendar.DATE);
		model.setPayDate(year + month + day + "");
		
		// 付款笔数
		model.setBatchNum(model.getRentalOrders().size());
		Date date = new Date();
		model.setCreateTime(new Timestamp(date.getTime()));
		genericService.add(model);
		return resultMeg;
	}
	
	/**
	 * 支付宝批量转账
	 * @param model
	 * @return 转账请求结果跳转页面
	 */
	private String batchTransByAlipay(BatchTransRentalRecord model) {
		BatchTransRecord batchTransRecord = new BatchTransRecord();
		
		// 批次号B+当前时间戳
		model.setBatchNo("B" + OrderUtil.getOrderNum());
		
		// 付款总金额
		model.setBatchFee(this.getTotalFee(model.getRentalOrders()));
		
		// 付款帐号
		model.setAccountEmail(AlipayConfig.SELLER_EMAIL);
		
		// 付款账户名
		model.setAccountName(AlipayConfig.SELLER_NAME);
		
		// 付款当天日期
		Calendar now = Calendar.getInstance();
		int year = now.get(Calendar.YEAR);
		int month = now.get(Calendar.MONTH) + 1;
		int day = now.get(Calendar.DATE);
		model.setPayDate(year + month + day + "");
		
		// 付款笔数
		model.setBatchNum(model.getRentalOrders().size());
		
		this.copyRental2PayRecord(model, batchTransRecord);
		
		// 调用支付宝接口
		String resultMeg = alipayService.batchTransRecords(batchTransRecord);
		
		// 新增批次记录
		model.setPayState(BatchTransRentalRecord.PAY_STATE_PAYING);
		genericService.add(model);
		
		return resultMeg;
	}
	
	public void copyRental2PayRecord(BatchTransRentalRecord model, BatchTransRecord batchTransRecord) {
		ModelUtil.copy(model, batchTransRecord, true);
		List<RentalOrder> rentalOrders = model.getRentalOrders();
		List<PayOrder> payOrders = new ArrayList<PayOrder>();
		if(CollectionUtils.isNotEmpty(rentalOrders)) {
			for(RentalOrder rentalOrder : rentalOrders) {
				PayOrder payOrder = new PayOrder();
				ModelUtil.copy(rentalOrder, payOrder, true);
				payOrders.add(payOrder);
			}
		}
		batchTransRecord.setPayOrders(payOrders);
	}
	
	private BigDecimal getTotalFee(List<RentalOrder> rentalOrders) {
		BigDecimal totalFee = new BigDecimal("0.00");
		for(RentalOrder rentalOrder : rentalOrders) {
			RentalOrder queryModel = new RentalOrder();
			queryModel.setId(rentalOrder.getId());
			rentalOrder = genericService.load(queryModel);
			totalFee = totalFee.add(rentalOrder.getTotalFee());
		}
		return totalFee;
	}
	
	/**
	 * 根据支付宝传递的body的值截取优惠券ID集合
	 * @param user_coupons
	 * @return 优惠券ID集合
	 */
	private List<Object> getCouponIds(String user_coupons) {
		List<Object> couponIds = new ArrayList<>();
		if(user_coupons.contains("user_coupons=")) {
			
			String[] bodys = user_coupons.split("=");
			if(bodys == null || bodys.length <= 1) {
				return couponIds;
			}
			String containsString = bodys[1];
			if(StringUtils.isNotBlank(containsString)) {
				if(containsString.contains(";")) {
					String[] coupons = containsString.split(";");
					if(coupons != null && coupons.length > 0) {
						for(String couponId : coupons) {
							couponIds.add(Integer.parseInt(couponId));
						}
					} 
				} else {
					couponIds.add(Integer.parseInt(containsString));
				}
			}
		}
		return couponIds;
	}
	
	/**
	 * 支付租金订单异步处理
	 */
	@Transactional
	@SuppressWarnings("rawtypes")
	@Rest(simpleServiceName = "anonymity", type = "free")
	public void requestResult() {
		HttpServletRequest request = ServletActionContext.getRequest();
		Map<String, String> params = new HashMap<String, String>();
		Map requestParams = request.getParameterMap();

		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			params.put(name, valueStr);
		}
		
		HttpServletResponse response = ServletActionContext.getResponse();
		PrintWriter out = null;
		try {
			out = response.getWriter();
			
			// 商户订单号
			String out_trade_no = new String(request.getParameter(
					"out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
			
			// 支付宝交易号
			String trade_no = new String(request.getParameter("trade_no")
					.getBytes("ISO-8859-1"), "UTF-8");

			// 交易状态
			String trade_status = new String(request.getParameter(
					"trade_status").getBytes("ISO-8859-1"), "UTF-8");
			
			//交易总金额对应实交总金额
			String total_fee = new String(request.getParameter(
					"total_fee").getBytes("ISO-8859-1"), "UTF-8");
			
			// 优惠券
			String user_coupons = new String(request.getParameter(
					"body").getBytes("ISO-8859-1"), "UTF-8");
			
			// 验证返回消息是否合法
			boolean isTrue = AlipayNotify.verify(params, AlipayConfig.SIGN_TYPE_APP_RSA);
			
			RentalOrder queryModel = new RentalOrder();
			queryModel.setOutTradeNo(out_trade_no);
			
			RentalOrder rentalOrder = genericService.searchAll(queryModel).getData(0);
			// 验证金额是否正确
			List<Object> couponIds =  null;
			if(StringUtils.isNotBlank(user_coupons)) {
				couponIds = this.getCouponIds(user_coupons);
				if(couponIds.size() > 0) {
					List<UserCoupon> userCouponList = genericService.load(UserCoupon.class, couponIds, true);
					BigDecimal totalFee = rentalOrder.getTotalFee();
					for(UserCoupon userCoupon : userCouponList) {
						BigDecimal amount = userCoupon.getCoupon().getAmount();
						totalFee = totalFee.subtract(amount);
					}
					if(!total_fee.equals(totalFee.toString())) {
						isTrue = false;
					}
				} else {
					if(rentalOrder == null || !total_fee.equals(rentalOrder.getTotalFee().toString())) {
						isTrue = false;
					}
				}
			} 
			
			PaymentRecord payModel = new PaymentRecord();
			FeeRecord feeRecord = rentalOrder.getFeeRecord();
			Timestamp payTime = null;
			if (isTrue) {
				if (trade_status.equals("TRADE_FINISHED")) {
					// 判断该笔订单是否在商户网站中已经做过处理
					// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
					// 如果有做过处理，不执行商户的业务程序
				} else if(trade_status.equals("TRADE_SUCCESS")) {
					
					//zpx 8.25 以下三行，其它没有做任何修改
					if( paidNoticeService.isPaidFromDaRoom(out_trade_no,trade_no,FeeRecord.FEE_PAYMODEL_ALIPAY)){
						return;
					}
					
					// 修改订单状态
					rentalOrder.setOrderState(RentalOrder.ORDER_STATE_PAYMENTED);
					rentalOrder.setHhzPay(true);
					rentalOrder.setAmountFee(new BigDecimal(total_fee));
					
					
					// 优惠券处理
					if(couponIds.size() > 0) {
						List<UserCoupon> userCouponList = genericService.load(UserCoupon.class, couponIds, true);
						
						for(UserCoupon userCoupon : userCouponList) {
							userCoupon.setRentalOrder(rentalOrder);
							userCoupon.setStatus(UserCoupon.STATUS_USED);
						}
					}
					payModel.setPayState(PaymentRecord.PAY_STATE_SUCCESS);
					
					// 修改费用状态
					// 更新FeeRecord记录 (已缴费)
					if(feeRecord != null) {
					    // 关闭feeRecord 
					    feeRecordService.closeFeeRecord(feeRecord, FeeRecord.FEE_PAYMODEL_ALIPAY);
						
						// 更新好好租（房东）费用记录
						Fee fee = addFeeAfterPay(feeRecord);
						
						//发送短信
						sendSmsAfterPay(rentalOrder, fee, feeRecord);
						
						logger.info("支付成功，订单号：" + out_trade_no);
						
						//判断房东是否参加了活动，参加了的话，生成在线补贴订单以及补贴的财务流水
						//attendActivityHandle(rentalOrder);
						
						// 新增手续费订单
						//this.addRentalOrderOfPoundage(rentalOrder);
					}
				} else {
					// 支付失败
					payModel.setPayState(PaymentRecord.PAY_STATE_FAILURE);
					logger.info("支付失败，订单号：" + out_trade_no);
				}
				// 3.新增||更新支付记录
				Date date = new Date();
				payTime = new Timestamp(date.getTime());
				payModel.setOutTradeNo(out_trade_no);
				payModel.setPayType(PaymentRecord.PAY_TYPE_ALIPAY);
				// 预订订单
				payModel.setOrderType(RaConstant.ORDER_TYPE_RENTAL);
				payModel.setTotalFee(rentalOrder.getTotalFee());
				payModel.setTradeNo(trade_no);
				payModel.setCreateTime(payTime);

				// 更新订单记录
				rentalOrder.setPaymentRecord(payModel);
				genericService.update(rentalOrder);
			} else {
				logger.error("支付租金订单返回消息非法");
			}
			
		} catch (IOException e) {
			logger.error("支付租金订单异步处理出错", e);
		} finally {
			if(out != null) {
				out.println("success");
				out.flush();
				out.close();
			}
		}
	}
	
	/**
	 * 支付后添加fee
	 * @param feeRecord
	 * @return
	 */
	private Fee addFeeAfterPay(FeeRecord feeRecord){
		Room dbRoom = genericService.load(feeRecord.getRoom());
		BigDecimal depositRecv = new BigDecimal(0.00);
	    BigDecimal deposit = feeRecord.getDepositActual();
	    try {
			depositRecv = new BigDecimal(dbRoom.getAgreement().getDeposit());
		} catch (Exception e) {
			logger.warn("押金金额转化出错，Agreement.id="+dbRoom.getAgreement().getId());
			deposit = new BigDecimal(0.00);
		}
		if (deposit == null) {
			deposit = depositRecv;
		}
		List<Fee> fees = dbRoom.getAgreement().getFees();
		if (fees == null || fees.size() == 0) {
			feeService.generateDepositFee(dbRoom.getAgreement(), depositRecv, deposit);
			feeRecord.setAmountRecv(feeRecord.getAmountRecv().subtract(deposit));
			feeRecord.setAmountActual(feeRecord.getAmountActual().subtract(deposit));
		}
	    
		// 更新好好租（房东）费用记录
		Fee fee = new Fee();
		feeRecordService.copyFeeRecord2Fee(feeRecord, fee);
		fee.setId(null);
		fee = feeService.updateFeeOriginal(fee);
		return fee;
	}
	
	/**
	 * 租客在线支付成功后发送短信给房东
	 * @param rentalOrder
	 * @param fee
	 * @param feeRecord
	 */
	private void sendSmsAfterPay(RentalOrder rentalOrder, Fee fee, FeeRecord feeRecord){
		
		// 时间段开始
		String dateBeginRecv = feeRecord.getDateBeginRecv();
		dateBeginRecv = DateTimeUtil.formatStringDate(dateBeginRecv, DateTimeUtil.ISO_DATE_FORMAT);
		// 时间段结束
		String dateEndRecv = feeRecord.getDateEndRecv();
		dateEndRecv = DateTimeUtil.formatStringDate(dateEndRecv, DateTimeUtil.ISO_DATE_FORMAT);
		
		String datetime = DateTimeUtil.formatDateTime(new Date(), "yyyy年MM月dd日HH点mm分");
		
		// 短信通知房东租客已交租
		String phone = fee.getLandlordUser().getPhone();
		Room room = rentalOrder.getRoom();
		Building building = room.getBuilding();
		String smsContent = building.getName() + "-" + room.getName() + "房租客" + room.getAgreement().getTenantUser().getName() 
				+ "，于" + datetime + "缴租金" + rentalOrder.getTotalFee() 
				+ "元（" + dateBeginRecv + "~" + dateEndRecv + "）。" 
				+ "因支付宝或微信的公账结算限制,资金将在1至3个工作日转入您的账户。";   
		if (smsService.sendMessage(phone,
				SmsLog.TYPE_REMINDER_LETTER, smsContent, true,
				fee.getLandlordUser().getLoginUser(), SmsService.CHANEL_NORMAL, null) == null) {
			logger.error("短信发送出错");
		} 
	}
	
	
	/**
	 * 批量处理已付款到商户帐号的租金订单（批量转账）
	 */
	@SuppressWarnings("rawtypes")
	@Rest(simpleServiceName = "anonymity", type = "free")
	public void requestBatchResult() {
		logger.info("===============into notify_url requestBatchResult method==============");
		HttpServletRequest request = ServletActionContext.getRequest();
		Map<String, String> params = new HashMap<String, String>();
		Map requestParams = request.getParameterMap();

		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			params.put(name, valueStr);
		}
		
		HttpServletResponse response = ServletActionContext.getResponse();
		PrintWriter out = null;
		try {
			out = response.getWriter();
			
			// 获取支付宝的通知返回参数
			// 批次号
			String batch_no = new String(request.getParameter("batch_no")
					.getBytes("ISO-8859-1"), "UTF-8");

			// 根据批次号查询所有关联订单
			BatchTransRentalRecord queryModel = new BatchTransRentalRecord();
			queryModel.setBatchNo(batch_no);
			BatchTransRentalRecord model = genericService
					.searchAll(queryModel).getData(0);

			List<RentalOrder> orders = model.getRentalOrders();

			// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
			String success_details = new String(request.getParameter(
					"success_details").getBytes("ISO-8859-1"), "UTF-8");
			
			// 批量付款数据中转账失败的详细信息
			String fail_details = new String(request.getParameter(
					"fail_details").getBytes("ISO-8859-1"), "UTF-8");
			
			List<Object> objects = new ArrayList<Object>();
			if (AlipayNotify.verify(params, AlipayConfig.SIGN_TYPE_MD5)) {// 验证成功
				logger.info(success_details);
				// 更新批次转账记录
				model.setPayState(BatchTransRentalRecord.PAY_STATE_SUCCESS);
				genericService.update(model);
				
				// 更新订单状态
				for (RentalOrder order : orders) {
					order.setOrderState(RentalOrder.ORDER_STATE_SUCCESS);
					objects.add(order);
					
					FeeRecord fee = order.getFeeRecord();
					int successCount = 0;
					String phone = fee.getLandlordUser().getPhone();
					String smsContent = fee.getRoom().getName() + "（房间名）"
							+ this.getOrderName(fee, "总费用")
							+ "房租已转入您的账户，请注意查收！";
					if (smsService.sendMessage(phone,
							SmsLog.TYPE_REMINDER_LETTER, smsContent, true,
							fee.getLandlordUser().getLoginUser(), SmsService.CHANEL_NORMAL, null) == null) {
						logger.error("短信发送出错");
					} else {
						successCount = 1;
						//房东短信条数-1
						landlordPurchaseService.reduceMessageCount(fee.getLandlordUser(), successCount);
					}
				}
				genericService.updateList(objects);
			} else {// 验证失败
				logger.info(fail_details);
			}
		} catch (IOException e) {
			logger.error("租金订单批量转账出错");
		} finally {
			if(out != null) {
				out.println("success");
				out.flush();
				out.close();
			}
		}
	}
	
	/**
	 * 根据费用信息查询对应订单
	 * @param fee
	 * @return 费用对应订单
	 */
	public RentalOrder searchRentalOrderByFeeRecord(FeeRecord feeRecord) {
		if (feeRecord == null) {
			return null;
		}
		RentalOrder queryRentalOrder = new RentalOrder();
		queryRentalOrder.setFeeRecord(feeRecord);
		queryRentalOrder.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		RentalOrder RentalOrder = null;
		if(feeRecord != null) {
			RentalOrder = genericService.searchAll(queryRentalOrder).getData(0);
		}
		return RentalOrder;
	}
	
	public RentalOrder searchRentalOrderByChargeBillRecord(DaChargeBillRecord chargeBillRecord) {
		if (chargeBillRecord == null) {
			return null;
		}
		RentalOrder example = new RentalOrder();
		example.setChargeBillRecord(chargeBillRecord);
		example.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		RentalOrder RentalOrder = null;
		if(chargeBillRecord != null) {
			RentalOrder = genericService.searchAll(example).getData(0);
		}
		return RentalOrder;
	}
	
	/**
	 * 判断临时计算费用与订单费用是否相等，如果相等则返回true，否则false
	 * @param model
	 * @return boolean true or false
	 */
	public boolean compareToFee(Fee model) {
		FeeRecord queryModel = new FeeRecord();
		queryModel.setRoom(model.getRoom());
		queryModel.setDateBeginRecv(model.getDateBeginRecv());
		queryModel.setDateEndRecv(model.getDateEndRecv());
		
		FeeRecord feeRecord = genericService.searchAll(queryModel).getData(0);
		
		if(feeRecord == null) {
			return true;
		}
		
		String dateBeginRecv = feeRecord.getDateBeginRecv();
		String dateEndRece = feeRecord.getDateEndRecv();
		BigDecimal amountRecv = feeRecord.getAmountRecv();
		BigDecimal amountActual = feeRecord.getAmountActual();
		
		if(!dateBeginRecv.equals(model.getDateBeginRecv()) || !dateEndRece.equals(model.getDateEndRecv()) 
				|| !amountRecv.equals(model.getAmountRecv()) || !amountActual.equals(model.getAmountActual())) {
			return false;
		}
		List<FeeAdditionRecord> RentalOrderFeeAdditions = feeRecord.getFeeAdditionRecords();
		List<FeeAddition> feeAdditions = model.getFeeAdditions();
		
		if(!Arrays.equals(RentalOrderFeeAdditions.toArray(), feeAdditions.toArray())) return false;
		return true;
	}
	
	/**
	 * 微信响应支付接口
	 * （接口：ra/pay/weixin/weixinPay.wxPay.html?goods.body=怡宝桶装水&goods.totalFee=1&goods.outTradeNo=11&openid=xxx）
	 * @param goods
	 * @param openid
	 * @return
	 * @throws ApplicationException
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	@Rest(simpleServiceName = "anonymity", type = "free")
	public Map<String, String> weixinNotifyPay() {
		System.out.println("===========into weixinNotifyPay===========");
		
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpServletResponse response = ServletActionContext.getResponse();
		StringBuilder sb = new StringBuilder();
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
	        String line = null;
			while((line = br.readLine())!=null){
			    sb.append(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		Map<String, String> map = new HashMap<String, String>();
		try {
			map = GetWxOrderno.doXMLParse(sb.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		// 总金额
		String totalFee = map.get("total_fee");
		// 订单号
		String outTradeNo = map.get("out_trade_no");
		// 微信订单号
		String transId = map.get("transaction_id");
		
		// 构造新的参数
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		for (Entry<String, String> entry : map.entrySet()) {
			String   key   = entry.getKey();
			String value = entry.getValue();
			if (null == value) {
				continue;
			} else {
				packageParams.put(key,value);
			}
		}
		
		PrintWriter out = null;
		try {
			out = response.getWriter();
			boolean temp = verifySign(packageParams, request, response);
			if (!temp) {
				System.out.println("校验支付error！");
			} else {
				// 业务处理
				if (StringUtils.isEmpty(outTradeNo)) {
					map.put("resultCode", RaConstant.WEIXIN_PAY_FAIL);
					logger.warn("支付失败");
				}
				else{
					
					map.put("resultCode", RaConstant.WEIXIN_PAY_SUCCESS);
					map.put("totalFee", totalFee);
					map.put("orderId", outTradeNo);
					map.put("totalFee", totalFee);
					logger.info("支付成功，订单号：" + outTradeNo);
					// 如果是分散式房源，则isPaidFromDaRoom，否则paySuccessHandle
					if(!paidNoticeService.isPaidFromDaRoom(outTradeNo,transId,PaymentRecord.PAY_TYPE_WEIXIN)){
						paySuccessHandle(outTradeNo, transId);
					}
				}
			}
		} catch (Exception e) {
			logger.error("微信支付异步回调出错！", e);
		} finally {
			if(out != null) {
				out.write("success");
				out.flush();
				out.close();
			}
		}
		return map;
	}
	
	
	/**
	 * 支付成功的操作处理
	 * 
	 * @param outTradeNo 系统订单号
	 * @param transId 微信订单号
	 */
	private void paySuccessHandle(String outTradeNo, String transId){
		RentalOrder queryModel = new RentalOrder();
		RentalOrder rentalOrder = new RentalOrder();
		PaymentRecord payModel = new PaymentRecord();
		queryModel.setOutTradeNo(outTradeNo);
		
		List<RentalOrder> rentalOrders = genericService.searchAll(queryModel).getData();
		
		// 可能存在多次回调的情况，需处理
		if (rentalOrders != null && rentalOrders.size() > 0) {
			rentalOrder = rentalOrders.get(0);
			if (rentalOrder.getOrderState() != RentalOrder.ORDER_STATE_WAITING_PAYMENT) {
				return;
			}
		}else{
			return;
		}
		
		// 修改订单状态"已付款"、支付状态“支付成功”
		rentalOrder.setOrderState(RentalOrder.ORDER_STATE_PAYMENTED);
		rentalOrder.setHhzPay(true);
		payModel.setPayState(PaymentRecord.PAY_STATE_SUCCESS);
		
		FeeRecord feeRecord = rentalOrder.getFeeRecord();
	    
	    // 关闭feeRecord 
	    feeRecordService.closeFeeRecord(feeRecord, FeeRecord.FEE_PAYMODEL_WECHAT);
		
		// 更新好好租（房东）费用记录
		
		Fee fee = addFeeAfterPay(feeRecord);
		
		// 3.新增||更新支付记录
		payModel.setOutTradeNo(outTradeNo);
		// 支付类型：微信支付
		payModel.setPayType(PaymentRecord.PAY_TYPE_WEIXIN);
		// 预订类型：交租订单
		payModel.setOrderType(RaConstant.ORDER_TYPE_RENTAL);
		payModel.setTotalFee(rentalOrder.getTotalFee());
		payModel.setTradeNo(transId);
		Date date = new Date();
		Timestamp payTime = new Timestamp(date.getTime());
		payModel.setCreateTime(payTime);
		//genericService.merge(payModel);
		
		// 更新订单记录
		rentalOrder.setPaymentRecord(payModel);
		genericService.update(rentalOrder);
		
		// 发送短信
		sendSmsAfterPay(rentalOrder, fee, feeRecord);
		
		logger.info("支付成功，订单号：" + outTradeNo);
		
		//判断房东是否参加了活动，参加了的话，生成在线补贴订单以及补贴的财务流水
		attendActivityHandle(rentalOrder);
		//feeService.getOrGenerateFeeRecordIfNotExists(rentalOrder.getRoom().getAgreement()); //产生下个月的代收费。
	}
	
	/**
	 * 参与活动的处理
	 * @param rentalOrder
	 */
	private void attendActivityHandle(RentalOrder rentalOrder){
		Room room = rentalOrder.getRoom();
		LandlordUser landlordUser = room.getLandlordUser();
		if (landlordUser.getAttendMilliActivity() != null && landlordUser.getAttendMilliActivity()) {
			//新增订单
			RentalOrder newRentalOrder = new RentalOrder();
			newRentalOrder.setTotalFee(RentalOrder.ACTIVITY_AMOUNT);
			newRentalOrder.setOrderDec(RentalOrder.ACTIVITY_NAME);
			newRentalOrder.setFeeRecord(rentalOrder.getFeeRecord());
			newRentalOrder.setRoom(room);
			addRentalOrderOfActivity(newRentalOrder);
			logger.info("新增百万活动在线交租房东补贴订单");
			//新增财务流水
			financeStatementService.createActivityStatementOfRa(room, RentalOrder.ACTIVITY_AMOUNT, RentalOrder.ACTIVITY_NAME);
			logger.info("新增百万活动房东交租财务流水记录");
		}
	}
	
	/**
     * 支付回调校验签名
     * @param timestamp
     * @param noncestr
     * @param openid
     * @param issubscribe
     * @param appsignature
     * @return
     * @throws UnsupportedEncodingException 
     */
    private boolean verifySign(SortedMap<String, String> map, HttpServletRequest req, HttpServletResponse res) throws Exception {
    	WeixinConfig weixinConfig = weixinUtil.getWeixinConfig();
    	//商户相关资料 
	    String appid = weixinConfig.getAppId();
	    
    	RequestHandler reqHandler = new RequestHandler(req, res);
		reqHandler.init(appid, weixinConfig.getSecret(), weixinConfig.getPartnerKey());
		
		String paySign = reqHandler.createSign(map);
		// sign
	    String sign = map.get("sign");
        return paySign.equalsIgnoreCase(sign);
    }
	
	/**
	 * 重新生成订单
	 * @param model 临时费用
	 * @return 成功标识 1：成功，0：失败
	 */
	@Transactional
	public RentalOrder updateRentalOrder(RentalOrder model, Integer feeRecordStatus) {
		
		FeeRecord dbFeeRecord = genericService.load(model.getFeeRecord());
		if (dbFeeRecord == null) {
			throw new ApplicationException("再次生成网上收租单时出现异常,未找到对应的FeeRecord");
		}
		
		this.deleteRentalOrder(model);
		return this.addRentalOrder(model, feeRecordStatus);
	}
	
	/**
	 * 更新订单状态
	 * @param id 订单ID
	 * @param orderState 更新状态
	 * @return 租金订单
	 */
	public RentalOrder updateOrderState(Integer id, Integer orderState) {
		RentalOrder queryModel = new RentalOrder();
		queryModel.setId(id);
		RentalOrder rentalOrder = genericService.load(queryModel);
		if(rentalOrder.getOrderState().equals(RentalOrder.ORDER_STATE_WAITING_PAYMENT)) {
			rentalOrder.setOrderState(orderState);
			return genericService.update(rentalOrder);
		} 
		return rentalOrder;
	}
	
	/**
	 * 订单删除
	 * @param model
	 * @return 成功标识 1：成功，0：失败
	 */
	public int deleteRentalOrder(RentalOrder model) {
		FeeRecord feeRecord = model.getFeeRecord();
		// TODO 测试环境部分人的帐号会出现删除报异常的情况
		feeRecord = genericService.load(feeRecord);
		RentalOrder queryModel = new RentalOrder();
		queryModel.setFeeRecord(feeRecord);
		queryModel.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		RentalOrder result = genericService.searchAll(queryModel).getData(0);
		
		if(result != null) {
			genericService.delete(result);
		}
		return RaConstant.OPERATE_SUCCESS;
	}
	
	/**
	 * 订单关闭
	 * @param feeRecord
	 * @return 订单
	 */
	public RentalOrder closeRentalOrder(FeeRecord feeRecord) {
		RentalOrder queryModel = new RentalOrder();
		queryModel.setFeeRecord(feeRecord);
		queryModel.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		RentalOrder exised = genericService.searchAll(queryModel).getData(0);
		
		RentalOrder result = null; 
		if(exised != null) { // 存在订单则执行更新操作
			exised.setOrderState(RentalOrder.ORDER_STATE_CLOSED);
			genericService.update(exised);
			
			// 关闭feeRecord 
		    feeRecordService.closeFeeRecord(feeRecord, FeeRecord.FEE_PAYMODEL_CASH);
		} else {
			exised = new RentalOrder();
			exised.setFeeRecord(feeRecord);
			exised.setOrderState(RentalOrder.ORDER_STATE_CLOSED);
			result = this.addRentalOrder(exised, FeeRecord.FEE_STATUS_RENT_DONE);
		}
		return result;
	}
	
	/**
	 * 收租订单处理
	 * @param feeRecord
	 * @return 订单
	 */
	public RentalOrder rentalOrderSuccess(FeeRecord feeRecord) {
		RentalOrder queryModel = new RentalOrder();
		queryModel.setFeeRecord(feeRecord);
		queryModel.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		RentalOrder exised = genericService.searchAll(queryModel).getData(0);
		
		RentalOrder result = null; 
		PaymentRecord payment = null;
		if(exised != null) { // 存在订单则执行更新操作
			payment = this.finishPaymentRecord(exised);
			exised.setPaymentRecord(payment);
			exised.setOrderState(RentalOrder.ORDER_STATE_SUCCESS);
			result = genericService.update(exised);
			
			// 关闭feeRecord 
		    feeRecordService.closeFeeRecord(feeRecord, FeeRecord.FEE_PAYMODEL_CASH);
		} else {
			exised = new RentalOrder();
			exised.setFeeRecord(feeRecord);
			exised.setOrderState(RentalOrder.ORDER_STATE_SUCCESS);
			result = this.addRentalOrder(exised, FeeRecord.FEE_STATUS_RENT_DONE);
			payment = this.finishPaymentRecord(result);
			result.setPaymentRecord(payment);
			result = genericService.update(result);
		}
		return result;
	}
	
	/**
	 * 现金收租支付记录
	 * @param rentalOrder
	 * @return PaymentRecord
	 */
	private PaymentRecord finishPaymentRecord(RentalOrder rentalOrder) {
		PaymentRecord payment = rentalOrder.getPaymentRecord();
		if (payment == null) {
			payment = new PaymentRecord();
		}
		payment.setPayState(PaymentRecord.PAY_STATE_SUCCESS);
		payment.setOutTradeNo(rentalOrder.getOutTradeNo());
		payment.setPayType(PaymentRecord.PAY_TYPE_CASH);
		payment.setOrderType(RaConstant.ORDER_TYPE_RENTAL);
		payment.setTotalFee(rentalOrder.getTotalFee());
		// 现金交易无交易号
		payment.setTradeNo("");
		Date date = new Date();
		Timestamp payTime = new Timestamp(date.getTime());
		payment.setCreateTime(payTime);
		return payment;
	}
	
	/**
	 * 根据登录用户查询费用对应租金订单集合
	 * @param model
	 * @return 租金订单集合
	 */
	public List<RentalOrder> searchRentalOrders(Integer orderState) {
		List<TenantUser> tenantUsers = tenantUserService.searchTenantUsersByLoginUser();
		List<RentalOrder> rentalOrders = new ArrayList<RentalOrder>();
		if(CollectionUtils.isEmpty(tenantUsers)) {
			return rentalOrders;
		}
		
		// 查询租客对应的RentalOrder
		for(TenantUser tenantUser : tenantUsers) {
			List<RentalOrder> results = this.searchRentalOrdersByTenantUser(tenantUser, orderState);
			if(CollectionUtils.isNotEmpty(results)) {
				rentalOrders.addAll(results);
			}
		}
		
		return rentalOrders;
	}
	
	/**
	 * 获取DA/RA的合约集合
	 * @return
	 */
	public List<OrderVO> searchRaDaAgreementByTenantUser(){
		List<OrderVO> lstOrderVO = new ArrayList<>();
		TenantUser tenantUserModel = new TenantUser();
		LoginUser loginUser = loginUserService.getLoginUser();
		// 用于测试
		//loginUser = genericService.load(LoginUser.class, 31);  
		tenantUserModel.setLoginUser(loginUser);
		
		List<TenantUser> tenantUsers = genericService.searchAll(tenantUserModel).getData();
		if (tenantUsers != null && tenantUsers.size() > 0) {
			for (TenantUser tenantUser : tenantUsers) {
				List<OrderVO> raOrderVO = searchRaAgreement(tenantUser);
				List<OrderVO> daOrderVO = searchDaAgreement(tenantUser);
				if (CollectionUtils.isNotEmpty(raOrderVO)) {
					lstOrderVO.addAll(raOrderVO);
				}
				if (CollectionUtils.isNotEmpty(daOrderVO)) {
					lstOrderVO.addAll(daOrderVO);
				}
			}
		}
		return lstOrderVO;
	}
	
	/**
	 * 通过租客查询DA合约集合（包含仪表费用信息及固定费用） 
	 * 
	 * （为租客APP而生）
	 * @return
	 */
	public List<OrderVO> searchRaAgreement(TenantUser tenantUser){
		Calendar now = Calendar.getInstance();
		List<OrderVO> lstOrderVO = new ArrayList<>();
		ValidAgreement modelAgreement = new ValidAgreement();
		modelAgreement.setTenantUser(tenantUser);
		List<ValidAgreement> lstValidAgreement = genericService.searchAll(modelAgreement).getData();
		if (CollectionUtils.isNotEmpty(lstValidAgreement)) {
			for (ValidAgreement validAgreement : lstValidAgreement) {
				//判断合约对应的房间是已收还是未收
				Room room = validAgreement.getRoom();
				if (room != null && room.getRentType() != null && room.getRentType() == Room.RENT_TYPE_ENTIRE) {
					if (room.getAgreement() != null) {
						if (room.getAgreement().getId() == null || room.getAgreement().getFees().size() <= 1 || DateTimeUtil.GetDateWithAdvanceNum(DateTimeUtil.StrToDate(room.getAgreement().getFees().get(0).getDateEndRecv()), room.getAgreement().getAdvanceNum()).compareTo(DateTimeUtil.throwTimeForDate(new Date())) < 0) {
							room.setHasPay(false);
						} else {
							room.setHasPay(true);
						}
					} else {
						room.setHasPay(false);
					}
				} else {
					//TODO: subRoom
				}
				
				FeeRecord queryModel = new FeeRecord();
				queryModel.setTenantUser(tenantUser);
				queryModel.setAgreement(validAgreement);
				List<FeeRecord> feeRecords = genericService.searchAll(queryModel).getData();
				FeeRecord resultFeeRecord = null;
				if (CollectionUtils.isNotEmpty(feeRecords)) {
					if (room != null && room.getHasPay() != null && room.getHasPay()) {
						Fee lastFee = validAgreement.getFees().get(0);
						for (int i = feeRecords.size(); i > 0; i--) {
							FeeRecord feeRecord = feeRecords.get(i - 1);
							
							//是否是提前收费（比如10月份收11月份的费用）
							boolean isAdvanceFee = false;
							if (DateTimeUtil.StrToDate(feeRecord.getDateBeginRecv()).after(DateTimeUtil.StrToDate(lastFee.getDateEndRecv()))) {
								isAdvanceFee = true;
							}
							
							//提前收费  或者 当前月收费
							if (isAdvanceFee || feeRecord.getDateBeginRecv().equals(
									lastFee.getDateBeginRecv())
									&& feeRecord.getDateEndRecv().equals(
											lastFee.getDateEndRecv())) {
								resultFeeRecord = feeRecord;
								break;
							}
						}
					}else{
						resultFeeRecord = feeRecords.get(feeRecords.size() - 1);
					}
				}
				// 获取OrderVO
				if (resultFeeRecord != null) {
					OrderVO orderVO = getOrderVOByFeeRecord(resultFeeRecord);
					lstOrderVO.add(orderVO);
				}
			}
		}
		
		return lstOrderVO;
	}
	
	/**
	 * 通过feeRecord获取OrderVO（集中式）
	 * @param feeRecord
	 * @return
	 */
	private OrderVO getOrderVOByFeeRecord(FeeRecord feeRecord){
		OrderVO orderVO = new OrderVO();
		Room room = feeRecord.getRoom();
		orderVO.setRoomId(room.getId());
		orderVO.setRoomName(room.getBuilding().getName() + "-" + room.getName());
		orderVO.setLandlordUser(room.getLandlordUser());
		String startDate = feeRecord.getDateBeginRecv();
		if (startDate != null) {
			startDate = startDate.substring(0, 10);
			startDate = startDate.replaceAll("-", "\\.");
		}
		String endDate = feeRecord.getDateEndRecv();
		if (endDate != null) {
			endDate = endDate.substring(0, 10);
			endDate = endDate.replaceAll("-", "\\.");
		}
		orderVO.setStartDate(startDate);
		orderVO.setEndDate(endDate);
		orderVO = commonService.completeOrderVO(orderVO);
		RentalOrder rentalOrderModel = new RentalOrder();
		rentalOrderModel.setFeeRecord(feeRecord);
		rentalOrderModel.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		List<RentalOrder> rentalOrders = genericService.search(rentalOrderModel, 0, 1000, "id", "desc", true).getData();
		if (CollectionUtils.isNotEmpty(rentalOrders)) {
			RentalOrder rentalOrder = rentalOrders.get(0);
			orderVO.setOrderId(rentalOrder.getId());
			orderVO.setOutTradeNo(rentalOrder.getOutTradeNo());
			orderVO.setTotalFee(rentalOrder.getTotalFee());
			orderVO.setOrderState(rentalOrder.getOrderState());
			OrderItemsVO totalFeeItem = new OrderItemsVO();
			totalFeeItem.setName("总费用");
			totalFeeItem.setPrice(rentalOrder.getTotalFee());
			List<OrderItemsVO> meterOrderItems = new ArrayList<OrderItemsVO>();
			List<OrderItemsVO> orderItems = new ArrayList<OrderItemsVO>();
			List<FeeAdditionRecord> feeAdditionRecords = feeRecord.getFeeAdditionRecords();
			
			//判断是否存在押金房租，如果存在，则加进来
			if(room.getAgreement()!=null && (room.getAgreement().getFees()==null||room.getAgreement().getFees().size()==0)){
				BigDecimal deposit = feeRecord.getDepositActual();
				if (deposit == null) {
					try {
						deposit = new BigDecimal(room.getAgreement().getDeposit());
					} catch (Exception e) {
						logger.warn("押金金额转化出错，Agreement.id="+room.getAgreement().getId());
						deposit = new BigDecimal(0.00);
					}
				}
				OrderItemsVO depositeItem = new OrderItemsVO();
				depositeItem.setName("押金");
				depositeItem.setPrice(feeRecord.getDepositActual());
				depositeItem.setUnitPrice(feeRecord.getDepositActual());
				orderItems.add(depositeItem);
			}
			if (feeRecord.getRental() != null) {
				OrderItemsVO rentalItem = new OrderItemsVO();
				rentalItem.setName("房租");
				rentalItem.setPrice(feeRecord.getRental());
				rentalItem.setUnitPrice(feeRecord.getRental());
				orderItems.add(rentalItem);
			}
			
			if(CollectionUtils.isNotEmpty(feeAdditionRecords)) {
				for(FeeAdditionRecord feeAddition : feeAdditionRecords) {
					FeeRuleCfg feeRuleCfg = feeAddition.getFeeRuleCfg();
					if(feeRuleCfg != null) {
						FeeRuleCfgDesc feeRuleCfgDesc = feeRuleCfg.getFeeRuleCfgDesc();
						FeeRuleCfgCalc feeRuleCfgCalc = feeRuleCfg.getFeeRuleCfgCalc();
						if(feeRuleCfgDesc != null) {
							FeeRuleType type = feeRuleCfgDesc.getType();
							OrderItemsVO orderItem = new OrderItemsVO();
							if(type == FeeRuleType.meter){
								Meter meter1 = feeAddition.getMeter1();
								Meter meter2 = feeAddition.getMeter2();
								orderItem.setCurrMeterCount(meter1.getCount());
								orderItem.setPreMeterCount(meter2.getCount());
								orderItem.setUnitPrice(feeRuleCfgCalc.getPrice());
								orderItem.setType(DaChargeItem.CHARGE_TYPE_METER);
								meterOrderItems.add(orderItem);
							}
							orderItem.setUnit(feeRuleCfgDesc.getUnit());
							orderItem.setName(feeRuleCfgDesc.getName());
							orderItem.setPrice(feeAddition.getPriceRecv());
							orderItems.add(orderItem);
						}
					}
				}
			}
			
			meterOrderItems.add(totalFeeItem);
			orderVO.setMeterItems(meterOrderItems);
			orderVO.setItems(orderItems);
		}
		return orderVO;
	}
	
	
	/**
	 * 通过租客查询DA合约集合（包含仪表费用信息及固定费用） 
	 * 
	 * （为租客APP而生）
	 * @return
	 */
	public List<OrderVO> searchDaAgreement(TenantUser tenantUser){
		List<OrderVO> lstOrderVO = new ArrayList<>();
		DaAgreement modelAgreement = new DaAgreement();
		modelAgreement.setTenantUser(tenantUser);
		modelAgreement.setAgreementState(DaAgreement.AGREEMENT_STATE_VALID);
		List<DaAgreement> lstValidAgreement = genericService.searchAll(modelAgreement).getData();
		if (CollectionUtils.isNotEmpty(lstValidAgreement)) {
			for (DaAgreement daAgreement : lstValidAgreement) {
				DaRoom daRoom = daAgreement.getRoom();
				if (daRoom != null) {
					OrderVO orderVO = new OrderVO();
					List<RentalOrder> rentalOrder = searchRentalOrdersByDaRoom(daRoom, RentalOrder.ORDER_STATE_WAITING_PAYMENT);
					if (CollectionUtils.isNotEmpty(rentalOrder)) {
						orderVO = paidNoticeService.getNoPayOrderVO(rentalOrder.get(0));
					}else{
						orderVO.setRoomName(daRoom.getName());
						orderVO.setRoomId(daRoom.getId());
					}
					lstOrderVO.add(orderVO);
				}
			}
		}
		return lstOrderVO;
	}
	
	/**
	 * 通过租客查询合约集合（包含仪表费用信息及固定费用） 
	 * 
	 * （为租客APP而生）
	 * @return
	 */
	public List<Agreement> searchAgreementByTenantUser(){
		
		List<Agreement> agreements = new ArrayList<>();
		TenantUser tenantUserModel = new TenantUser();
		LoginUser loginUser = loginUserService.getLoginUser();
		// 用于测试
		//loginUser = genericService.load(LoginUser.class, 31);  
		tenantUserModel.setLoginUser(loginUser);
		
		List<TenantUser> tenantUsers = genericService.searchAll(tenantUserModel).getData();
		if (tenantUsers != null && tenantUsers.size() > 0) {
			for(TenantUser tenantUser : tenantUsers) {
				ValidAgreement modelAgreement = new ValidAgreement();
				modelAgreement.setTenantUser(tenantUser);
				List<ValidAgreement> lstValidAgreement = genericService.searchAll(modelAgreement).getData();
				if (CollectionUtils.isNotEmpty(lstValidAgreement)) {
					for (ValidAgreement validAgreement : lstValidAgreement) {
						FeeRecord queryModel = new FeeRecord();
						queryModel.setTenantUser(tenantUser);
						queryModel.setAgreement(validAgreement);
						List<FeeRecord> feeRecords = genericService.searchAll(queryModel).getData();
						if (CollectionUtils.isNotEmpty(feeRecords)) {
							//填充固定费用、仪表费用
							FeeRecord resultFeeRecord = feeRecords.get(feeRecords.size() - 1);
							fillInFeeRecord(resultFeeRecord);
							validAgreement.setLastFeeRecord(resultFeeRecord);
							agreements.add(validAgreement);
						}
					}
				}
			}
		}
		
		return agreements;
	}
	
	/**
	 * 补全FeeRecord固定费用，及仪表费用（为租客APP而生）
	 * @param feeRecord
	 */
	private void fillInFeeRecord(FeeRecord feeRecord){
		
		//填充订单号
		RentalOrder rentalOrderModel = new RentalOrder();
		rentalOrderModel.setFeeRecord(feeRecord);
		rentalOrderModel.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		List<RentalOrder> rentalOrders = genericService.search(rentalOrderModel, 0, 1000, "id", "desc", true).getData();
		if (CollectionUtils.isNotEmpty(rentalOrders)) {
			feeRecord.setRentalOrderId(rentalOrders.get(0).getId());
			
			BigDecimal fixedFeeTemp = new BigDecimal("0.0");
			List<FeeAdditionRecord> meterFeeAdditionRecords = new ArrayList<>();
			List<FeeAdditionRecord> feeAdditionRecords = feeRecord.getFeeAdditionRecords();
			if(CollectionUtils.isNotEmpty(feeAdditionRecords)) {
				for(FeeAdditionRecord feeAddition : feeAdditionRecords) {
					FeeRuleCfg feeRuleCfg = feeAddition.getFeeRuleCfg();
					if(feeRuleCfg != null) {
						FeeRuleCfgDesc feeRuleCfgDesc = feeRuleCfg.getFeeRuleCfgDesc();
						if(feeRuleCfgDesc != null) {
							FeeRuleType type = feeRuleCfgDesc.getType();
							if(type == FeeRuleType.fixed) {
								fixedFeeTemp = fixedFeeTemp.add(feeAddition.getPriceRecv());
							}else if(type == FeeRuleType.meter){
								meterFeeAdditionRecords.add(feeAddition);
							}
						}
					}
				}
			}
			feeRecord.setFixedFeeTotalAmount(fixedFeeTemp);
			feeRecord.setMeterFeeAdditionRecords(meterFeeAdditionRecords);
		}
	}
	
	/**
	 * 根据租客和订单状态查询对应订单记录
	 * @param tenantUser
	 * @param orderState
	 * @return 订单记录
	 */
	public List<RentalOrder> searchRentalOrdersByTenantUser(TenantUser tenantUser, Integer orderState) {
		List<RentalOrder> rentalOrders = new ArrayList<RentalOrder>();
		if(tenantUser == null) {
			return rentalOrders;
		}
		
		RentalOrder queryModel = new RentalOrder();
		queryModel.setTenantUser(tenantUser);
		queryModel.setOrderState(orderState);
		rentalOrders = genericService.searchAll(queryModel).getData();
		if(CollectionUtils.isNotEmpty(rentalOrders)) {
			this.getOrderStateShow(rentalOrders);
		}
		return rentalOrders;
	}
	
	private List<RentalOrder> handleFixedFeeTotalAmount(List<RentalOrder> rentalOrders) {
		for(RentalOrder rentalOrder : rentalOrders) {
			BigDecimal fixedFeeTemp = new BigDecimal("0.0");
			FeeRecord feeRecord = rentalOrder.getFeeRecord();
			if(feeRecord != null) {
				List<FeeAdditionRecord> feeAdditionRecords = feeRecord.getFeeAdditionRecords();
				if(CollectionUtils.isEmpty(feeAdditionRecords)) {
					break;
				}
				for(FeeAdditionRecord feeAddition : feeAdditionRecords) {
					FeeRuleCfg feeRuleCfg = feeAddition.getFeeRuleCfg();
					if(feeRuleCfg != null) {
						FeeRuleCfgDesc feeRuleCfgDesc = feeRuleCfg.getFeeRuleCfgDesc();
						if(feeRuleCfgDesc != null) {
							FeeRuleType type = feeRuleCfgDesc.getType();
							if(type == FeeRuleType.fixed) {
								fixedFeeTemp = fixedFeeTemp.add(feeAddition.getPriceRecv());
							}
						}
					}
				}
				feeRecord.setFixedFeeTotalAmount(fixedFeeTemp);
				rentalOrder.setFeeRecord(feeRecord);
			}
		}
		return rentalOrders;
	}
	

	
	/**
	 * 根据登录用户查询对应的房屋信息(NEW)
	 * @return 房屋集合
	 */
	public List<AgreementVO> searchRoomsNew() {
		List<AgreementVO> agreementVOs = new ArrayList<>();
		List<AgreementVO> noOrderAgreementVOs = new ArrayList<>();
		List<TenantUser> tenantUsers = tenantUserService.searchTenantUsersByLoginUser();
		//租客绑定
		repairBangingUser(tenantUsers);
		
		if (CollectionUtils.isNotEmpty(tenantUsers)) {
			for (TenantUser tenantUser : tenantUsers) {
				//集中式房源
				ValidAgreement modelRaAgreement = new ValidAgreement();
				modelRaAgreement.setTenantUser(tenantUser);
				List<ValidAgreement> lstValidAgreement = genericService.searchAll(modelRaAgreement).getData();
				agreementVOs.addAll(convertAgreementVOFromRA(lstValidAgreement, noOrderAgreementVOs));
				
				//分散式房源
				DaAgreement modelDaAgreement = new DaAgreement();
				modelDaAgreement.setTenantUser(tenantUser);
				modelDaAgreement.setAgreementState(DaAgreement.AGREEMENT_STATE_VALID);
				List<DaAgreement> lstValidDaAgreement = genericService.searchAll(modelDaAgreement).getData();
				agreementVOs.addAll(convertAgreementVOFromDA(lstValidDaAgreement, noOrderAgreementVOs));
			}
		}
		agreementVOs.addAll(noOrderAgreementVOs);
		
		return agreementVOs;
	}
	
	/**
	 * List<Agreement> 转 List<AgreementVO>
	 * @param agreements
	 * @return
	 */
	public List<AgreementVO> convertAgreementVOFromRA(List<ValidAgreement> agreements, List<AgreementVO> noOrderAgreementVOs){
		List<AgreementVO> agreementVOs = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(agreements)) {
			for (Agreement agreement : agreements) {
				AgreementVO agreementVO = new AgreementVO();
				Room room = agreement.getRoom();
				agreementVO.setRoomId(room.getId());
				agreementVO.setRoomName(room.getName());
				agreementVO.setRoomType(LandlordConstant.ROOMTYPE_RA);
				List<RoomAttachment> roomAttachments = room.getRoomAttachments();
				if (CollectionUtils.isNotEmpty(roomAttachments)) {
					agreementVO.setRoomImageSrc(room.getRoomAttachments().get(0).getAttachmentFileName());
				}
				Date beginDate = DateTimeUtil.StrToDate(agreement.getRentBeginDate(), DateTimeUtil.DATETIME_FORMAT);
				agreementVO.setRentBeginDate(beginDate);
				Date endDate = DateTimeUtil.StrToDate(agreement.getRentEndDate(), DateTimeUtil.DATETIME_FORMAT);
				agreementVO.setRentEndDate(endDate);
				agreementVO.setLandlordUser(agreement.getLandlordUser());
				
				BigDecimal deposit = new BigDecimal(0.00);
				if (StringUtils.isNotBlank(agreement.getDeposit())) {
					deposit = new BigDecimal(agreement.getDeposit());
				}
				
				agreementVO.setDeposit(deposit);
				agreementVO.setRentPay(agreement.getRentPay());
				
				agreementVO.setTenantUser(agreement.getTenantUser());
				agreementVO.setAddress(room.getBuilding().getDetailAddress());
				agreementVO.setFloorName(String.valueOf(room.getBuildingFloor().getName()));
				agreementVO.setArea(room.getArea());
				List<FeeRule> feeRules = room.getFeeRules();
				List<FeeRuleCfg> feeRuleCfgs = new ArrayList<FeeRuleCfg>();
				for(FeeRule feeRule : feeRules){
					feeRuleCfgs.add(feeRule.getFeeRuleCfg());
				}
				agreementVO.setFeeRuleCfgs(feeRuleCfgs);
				//是否能交租
				//agreementVO.set
				List<RentalOrder> rentalOrders = searchRentalOrdersByRoom(room, RentalOrder.ORDER_STATE_WAITING_PAYMENT);
				if (CollectionUtils.isNotEmpty(rentalOrders)) {
					agreementVO.setHasTodoOrder(true);
					agreementVO.setRentalOrderId(rentalOrders.get(0).getId());
					LandlordUser landLordUser = room.getLandlordUser();
					// 判断房东是否设置银行卡
					if(landLordUser != null && landLordUser.getExistAlipayCard()) {
						agreementVOs.add(agreementVO);
					} else {
						noOrderAgreementVOs.add(agreementVO);
					}
				}else{
					agreementVO.setHasTodoOrder(false);
					noOrderAgreementVOs.add(agreementVO);
				}
			}
		}
		return agreementVOs;
	}
	
	/**
	 * List<DaAgreement> 转 List<AgreementVO>
	 * @param agreements
	 * @return
	 */
	public List<AgreementVO> convertAgreementVOFromDA(List<DaAgreement> agreements, List<AgreementVO> noOrderAgreementVOs){
		List<AgreementVO> agreementVOs = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(agreements)) {
			for (DaAgreement agreement : agreements) {
				AgreementVO agreementVO = new AgreementVO();
				DaRoom daRoom = agreement.getRoom();
				agreementVO.setRoomId(daRoom.getId());
				agreementVO.setRoomName(daRoom.getName());
				agreementVO.setRoomType(LandlordConstant.ROOMTYPE_DA);
				if (CollectionUtils.isNotEmpty(daRoom.getSuite().getAttachments())) {
					agreementVO.setRoomImageSrc(daRoom.getSuite().getAttachments().get(0).getAttachmentFileName());
				}
				agreementVO.setRentBeginDate(agreement.getRentBeginDate());
				agreementVO.setRentEndDate(agreement.getRentEndDate());
				agreementVO.setLandlordUser(agreement.getLandlordUser());
				agreementVO.setDeposit(agreement.getDeposit());
				agreementVO.setRentPay(agreement.getRentPay());
				agreementVO.setTenantUser(agreement.getTenantUser());
				Address address = daRoom.getSuite().getAddress();
				if (address != null) {
					agreementVO.setAddress(address.getName());
				}
				agreementVO.setFloorName(String.valueOf(daRoom.getSuite().getFloorNo()));
				agreementVO.setArea(daRoom.getArea());
				List<DaFeeRule> feeRules = daRoom.getFeeRules();
				List<FeeRuleCfg> feeRuleCfgs = new ArrayList<FeeRuleCfg>();
				for(DaFeeRule feeRule : feeRules){
					feeRuleCfgs.add(feeRule.getFeeRuleCfg());
				}
				agreementVO.setFeeRuleCfgs(feeRuleCfgs);
				//是否能交租
				//agreementVO.set
				
				List<RentalOrder> rentalOrders = searchRentalOrdersByDaRoom(daRoom, RentalOrder.ORDER_STATE_WAITING_PAYMENT);
				if (CollectionUtils.isNotEmpty(rentalOrders)) {
					agreementVO.setHasTodoOrder(true);
					agreementVO.setRentalOrderId(rentalOrders.get(0).getId());
					LandlordUser landLordUser = daRoom.getLandlordUser();
					// 判断房东是否设置银行卡
					if(landLordUser != null && landLordUser.getExistAlipayCard()) {
						agreementVOs.add(agreementVO);
					} else {
						noOrderAgreementVOs.add(agreementVO);
					}
				}else{
					agreementVO.setHasTodoOrder(false);
					noOrderAgreementVOs.add(agreementVO);
				}
			}
		}
		return agreementVOs;
	}
	
	private void repairBangingUser(List<TenantUser> tenantUsers) {
		LoginUser loginUser = loginUserService.getLoginUser();
		String name = loginUser.getName();
		if(CollectionUtils.isEmpty(tenantUsers)) {
			// 修正历史数据，一个租客对应多个loginId，导致当前登录loginId对应的租客找不到正确的房屋信息
			// 电话号码查询LoginUser
			TenantUser queryModel = new TenantUser();
	    	queryModel.setPhone(name);
	    	tenantUsers = genericService.searchAll(queryModel).getData();
	    	
	    	// 微信租客绑定修正
			// 电话号码查询weixinuser，若存在则更新
			WeixinUser queryUser = new WeixinUser();
			queryUser.setPhone(name);
			List<WeixinUser> weixinUsers = genericService.searchAll(queryUser).getData();
			boolean isWeixinUser = false;
			if(CollectionUtils.isNotEmpty(weixinUsers)) {
				
				if (weixinUsers.size() > 1) {
					for(WeixinUser weixinUser : weixinUsers) {
						if(StringUtils.isNotBlank(weixinUser.getOpenid())) {
							isWeixinUser = true;
						} else{
							genericService.delete(weixinUser);
						}
					}
				}
			}
	    	
	    	if(CollectionUtils.isNotEmpty(tenantUsers)) {
	    		for(TenantUser tenantUser : tenantUsers) {
	    			if (isWeixinUser) {
	    				tenantUser.setRelatedWeixin(true);
					}
	    			tenantUser.setLoginUser(loginUser);
	    			genericService.merge(tenantUser);
	    		}
	    	} 
		} else {
			for(TenantUser tenantUser : tenantUsers) {
				if (!name.equals(tenantUser.getPhone())) {
					tenantUser.setPhone(name);
					genericService.merge(tenantUser);
				}
			}
		}
	}
	
	/**
	 * 根据登录用户查询对应的房屋信息
	 * @return 房屋集合
	 */
	@SuppressWarnings("unchecked")
	public Map<Integer, Room> searchRooms() {
		Map<Integer, Room> roomMap = ListOrderedMap.decorate(new HashMap<Integer, Room>());
		Map<Integer, Room> tmpMap = ListOrderedMap.decorate(new HashMap<Integer, Room>());
		List<TenantUser> tenantUsers = tenantUserService.searchTenantUsersByLoginUser();
		
		// 查询租客对应的房间
		ValidAgreement queryModel = null;
		for(TenantUser tenantUser : tenantUsers) {
			queryModel = new ValidAgreement();
			// 0有效，1无效
			queryModel.setTenantUser(tenantUser);
			
			List<ValidAgreement> agreements = genericService.searchAll(queryModel).getData();
			for(ValidAgreement exised : agreements) {
				if(exised != null && exised.getRoom() != null) {
					Room room = exised.getRoom();
					String tenantUserName = exised.getTenantUser().getName();
					room.setTenantUserName(tenantUserName);
					
					//设置该房间是否有未缴费的订单
					List<RentalOrder> rentalOrders = searchRentalOrdersByRoom(room, RentalOrder.ORDER_STATE_WAITING_PAYMENT);
					if (rentalOrders != null && rentalOrders.size() > 0) {
						room.setHasTodoOrder(true);
						room.setRentalOrderId(rentalOrders.get(0).getId());
						LandlordUser landLordUser = room.getLandlordUser();
						// 判断房东是否设置银行卡
						if(landLordUser != null && landLordUser.getExistAlipayCard()) {
							roomMap.put(exised.getRoom().getId(), room);
						} else {
							tmpMap.put(exised.getRoom().getId(), room);
						}
					}else{
						room.setHasTodoOrder(false);
						tmpMap.put(exised.getRoom().getId(), room);
					}
				}
			}
		}
		roomMap.putAll(tmpMap);
		return roomMap;
	}
	
	/**
	 * 根据房间和订单状态查询对应租金订单(DA)
	 * @param model
	 * @param orderState
	 * @return 订单集合
	 */
	public List<RentalOrder> searchRentalOrdersByDaRoom(DaRoom model, Integer orderState) {
		RentalOrder queryModel = new RentalOrder();
		
		if (model.getAgreement() == null) {
			model = genericService.load(model);
		}
		
		queryModel.setDaRoom(model);
		if(model.getAgreement() != null && model.getAgreement().getTenantUser() != null) {
			queryModel.setTenantUser(model.getAgreement().getTenantUser());
		}
		queryModel.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		if(orderState != null) {
			queryModel.setOrderState(orderState);
		}
		String strShort = "createTime";
		String strOrderBy = "DESC";
		List<RentalOrder> rentalOrders = genericService.search(queryModel, 0,
				500, strShort, strOrderBy, false, null, null, true, false).getData();
		return rentalOrders;
	}
	
	/**
	 * 根据房间和订单状态查询对应租金订单集合
	 * @param model
	 * @param orderState
	 * @return 订单集合
	 */
	public List<RentalOrder> searchRentalOrdersByRoom(Room model, Integer orderState) {
		RentalOrder queryModel = new RentalOrder();
		
		if (model.getAgreement() == null) {
			model = genericService.load(model);
		}
		
		queryModel.setRoom(model);
		if(model != null && model.getAgreement() != null && model.getAgreement().getTenantUser() != null) {
			queryModel.setTenantUser(model.getAgreement().getTenantUser());
		}
		queryModel.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		if(orderState != null) {
			queryModel.setOrderState(orderState);
		}
		
		String strShort = "createTime";
		String strOrderBy = "DESC";
		List<RentalOrder> rentalOrders = genericService.search(queryModel, 0,
				500, strShort, strOrderBy, false, null, null, true, false).getData();
		Iterator<RentalOrder> rentalOrderIter = rentalOrders.iterator();
		while(rentalOrderIter.hasNext()) {
			RentalOrder rentalOrder = rentalOrderIter.next();
				rentalOrder.setSmallImgPath(this.getSmallImagePath(rentalOrder.getRentalVoucherFileName(), 
						RentalOrder.RENTALVOUCHER_SMALL_IMAGE));
				rentalOrder.setBigImgPath(this.getSmallImagePath(rentalOrder.getRentalVoucherFileName(), 
						RentalOrder.RENTALVOUCHER_BIG_IMAGE));
		}
		return rentalOrders;
	}
	
	/**
	 * 上传支付截图
	 * @param model
	 */
	@Transactional
	public Result uploadImage(RentalOrder model, String returnURL) {
		Result result = null;
		boolean isSendMessage = false;
		try{
			RentalOrder updateOrder = genericService.load(model);
			if(StringUtils.isNotBlank(model.getRentalVoucherFileName()) && 
					StringUtils.isBlank(updateOrder.getRentalVoucherFileName()) && 
					updateOrder.getOrderState() == RentalOrder.ORDER_STATE_WAITING_PAYMENT) {
				isSendMessage = true;
			}
			updateOrder.setRentalVoucherFileName(model.getRentalVoucherFileName());
			updateOrder.setRentalVoucher(model.getRentalVoucher());
			updateOrder.setRentalVoucherPayType(model.getRentalVoucherPayType());
			genericService.update(updateOrder);
			
			String payTypeShow = this.getPayTypeShow(updateOrder.getRentalVoucherPayType());
			
			String timeInterval = "";
			String orderName = updateOrder.getOrderName();
			if (StringUtils.isNotBlank(orderName) && orderName.length() > 2) {
				int begin = orderName.lastIndexOf('(');
				int end = orderName.lastIndexOf(')');
				timeInterval = orderName.substring(begin + 1, end);
			}
			
			String phone = "";
			String roomName = "";
			String tenantUserName = "";
			LoginUser loginUser = null;
			if (updateOrder.getRoomType() != null && LandlordConstant.ROOMTYPE_DA == updateOrder.getRoomType()) {
				DaRoom daRoom = updateOrder.getDaRoom();
				if (daRoom != null) {
					DaSuite daSuite = daRoom.getSuite();
					phone = daRoom.getLandlordUser().getPhone();
					Integer rentType = daSuite.getRentType();
					if (rentType != null && DaSuite.RENT_TYPE_ENTIRE == rentType) {
						roomName = daRoom.getName();
					}else{
						roomName = daSuite.getName() + "-" + daRoom.getName();
					}
					tenantUserName = daRoom.getAgreement().getTenantUser().getName();
					loginUser = daRoom.getLandlordUser().getLoginUser();
				}
			}else{
				Room room = updateOrder.getRoom();
				Building building = room.getBuilding();
				roomName = building.getName() + "-" + room.getName();
				phone = room.getLandlordUser().getPhone();
				tenantUserName = room.getAgreement().getTenantUser().getName();
				loginUser = room.getLandlordUser().getLoginUser();
			}
			
			if(isSendMessage) {
				// 短信通知房东租客已上传截图
				String smsContent = roomName + "房租客" + tenantUserName + "，已通过"
						+ payTypeShow + "交租" + updateOrder.getTotalFee() + "元（"
						+ timeInterval + "），" + "并在“好好租”平台上上传交易截图，请及时查收。";
				if (smsService.sendMessage(phone, SmsLog.TYPE_REMINDER_LETTER,
						smsContent, true, loginUser, SmsService.CHANEL_NORMAL,
						null) == null) {
					logger.error("上传支付截图过程中短信发送出错");
				} 
			}
			result = new ServletRedirectResult(returnURL);
			objectFactory.autoWireBean(result);
		} catch (Exception e) {
			logger.error("上传失败", e);
			throw new ApplicationException("上传失败");
		}
		return result;
	}
	
	/**
	 * 获取上传方式对应中文注释
	 * @return
	 */
	private String getPayTypeShow(Integer payType) {
		if(payType == null) {
			return "";
		}
		String payTypeShow = "";
		switch (payType) {
			case PaymentRecord.PAY_TYPE_WEIXIN:
				payTypeShow = "微信支付";
				break;
			case PaymentRecord.PAY_TYPE_BANK:
				payTypeShow = "网银支付";
				break;
			case PaymentRecord.PAY_TYPE_ALIPAY:
				payTypeShow = "支付宝支付";
				break;
			case PaymentRecord.PAY_TYPE_CASH:
				payTypeShow = "现金支付";
				break;
			default:
				break;
		}
		return payTypeShow;
	}
	
	/**
	 * 获取上传截图缩略图
	 * @param imgSrc
	 * @param resolution
	 * @return
	 */
	public String getSmallImagePath(String imgSrc, String resolution) {
		if(StringUtils.isBlank(imgSrc)) {
			return null;
		}
		Config config = Config.getInstance();
		String uploadRootPath = config.getUploadRootDir() + config.getUploadDir() + "RentalOrder" + "/";
		String oldImageSrc = config.getRealWebRootPath() + config.getSitePath()
				+ imgSrc;
		File roomAttachmentFile = new File(oldImageSrc);
		String attachmentFileName = roomAttachmentFile.getName();
		String newImageFile = resolution + "-" 
				+ attachmentFileName;
		String newImageSrc = config.getSitePath() + config.getUploadDir()
				+ "RentalOrder" + "/" + newImageFile;
		String newPath = uploadRootPath + newImageFile;
		File file = new File(newPath);
		if (!file.exists()) {
			String[] resString = resolution.split("x");
			if (roomAttachmentFile.exists()) {
				ImageUtils.zoomInImage(roomAttachmentFile, newPath,
						Integer.parseInt(resString[0]),
						Integer.parseInt(resString[1].toString()));
			} 
		}
		return newImageSrc;
	}
	
	/**
	 * 根据订单ID查询交租订单
	 * @param orderId
	 * @return 交租订单
	 */
	public RentalOrder readRentalOrderById(Integer orderId) {
		RentalOrder rentalOrder = genericService.load(RentalOrder.class, orderId);
		if(rentalOrder != null) {
			rentalOrder.setSmallImgPath(this.getSmallImagePath(rentalOrder.getRentalVoucherFileName(), 
					RentalOrder.RENTALVOUCHER_SMALL_IMAGE));
		}
		return rentalOrder;
	}
	
	/**
	 * 根据RentalOrderId查询订单（APP进入支付页面接口）
	 * @param orderId
	 * @return
	 */
	public OrderVO getOrderByRentalOrder(Integer orderId){
		OrderVO orderVO = null;
		RentalOrder rentalOrder = genericService.load(RentalOrder.class, orderId);
		if (rentalOrder != null) {
			rentalOrder.setSmallImgPath(this.getSmallImagePath(rentalOrder.getRentalVoucherFileName(), 
					RentalOrder.RENTALVOUCHER_SMALL_IMAGE));
			rentalOrder.setBigImgPath(this.getSmallImagePath(rentalOrder.getRentalVoucherFileName(), 
					RentalOrder.RENTALVOUCHER_BIG_IMAGE));
		}
		if (rentalOrder.getRoomType() != null && rentalOrder.getRoomType() == LandlordConstant.ROOMTYPE_DA) {
			// 分散式
			orderVO = paidNoticeService.getNoPayOrderVO(rentalOrder);
		}else if(rentalOrder.getFeeRecord() != null){
			// 集中式
			orderVO = getOrderVOByFeeRecord(rentalOrder.getFeeRecord());
		}
		if (orderVO != null && rentalOrder != null) {
			orderVO.setSmallImgPath(rentalOrder.getSmallImgPath());
			orderVO.setBigImgPath(rentalOrder.getBigImgPath());
			orderVO.setOrderDec(rentalOrder.getOrderDec());
			orderVO.setOrderName(rentalOrder.getOrderName());
			orderVO.setOrderState(rentalOrder.getOrderState());
			//添加手续费
			//orderVO = addPoundageTemp(orderVO);
		}
		
		return orderVO;
	}
	
	/**
	 * 临时添加手续费
	 * @param orderVO
	 * @return
	 */
	private OrderVO addPoundageTemp(OrderVO orderVO) {
		if (orderVO != null && orderVO.getLandlordUser() != null) {
			LandlordUser landlordUser = orderVO.getLandlordUser();
			
			// 需要添加手续费
			if (isAddPoundage(landlordUser)) {
				//1.5 %的手续费
				OrderItemsVO item = new OrderItemsVO();
				item.setName("手续费");
				BigDecimal price = orderVO.getTotalFee().multiply(RentalOrder.POUNDAGE_RATE);
				price = price.setScale(2, BigDecimal.ROUND_HALF_UP);
				item.setPrice(price);
				item.setStartDate(orderVO.getStartDate());
				item.setEndDate(orderVO.getEndDate());
				item.setType(RentalOrder.ORDERTYPE_POUNDAGE);
				List<OrderItemsVO> items = orderVO.getItems();
				if (items == null) {
					items = new ArrayList<>();
					orderVO.setItems(items);
				}
				items.add(item);
			}
				
		}
		return orderVO;
	}
	
	/**
	 * 是否需要手续费
	 * @param landlordUser
	 * @return
	 */
	private boolean isAddPoundage(LandlordUser landlordUser){
		boolean result = false;
		LandlordEstimation landlordEstimation = landlordEstimationService.searchLandlordByPhone(landlordUser.getPhone());
		Integer scope = null;
		if(landlordEstimation != null) {
			scope = landlordEstimation.getScope();
		}
		if ((landlordUser.getCertification() == null || !landlordUser.getCertification()) && (scope == null || scope < 3)) {
			result = true;
		}
		return result;
	}
	
	/**
	 * 查询当前登录租客的订单
	 * @return
	 */
	public OrderVO searchMyOrderVO(){
		OrderVO orderVO = null;
		List<RentalOrder> rentalOrders = searchRentalOrders(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
		if (CollectionUtils.isNotEmpty(rentalOrders)) {
			orderVO = getOrderByRentalOrder(rentalOrders.get(0).getId());
		}
		return orderVO;
	}
	
	/**
	 * 订单关闭，只操作订单
	 * @return 交租订单
	 */
	public RentalOrder closeRentalOrderById(Integer orderId) {
		RentalOrder rentalOrder = genericService.load(RentalOrder.class, orderId);
		if(rentalOrder != null) {
			rentalOrder.setOrderState(RentalOrder.ORDER_STATE_CLOSED);
			rentalOrder = genericService.update(rentalOrder);
		}
		return rentalOrder;
	}
	
	
	public boolean deleteRentalOrderBy(DaSuite suite){
		if(suite==null)return false;
		List<DaRoom> rooms = suite.getRooms();
		for (DaRoom daRoom : rooms) {
			RentalOrder deleteObject = new RentalOrder();
			deleteObject.setDaRoom(daRoom);
			List<RentalOrder> datas = genericService.searchByModel(deleteObject, Condition.DEFAULT).getData();
			if(datas.size()>0){
				for (RentalOrder rentalOrder : datas) {
					genericService.delete(rentalOrder);
				}
			}
		}
		return true;
	}
	
	/**
	 * 根据楼ID删除楼对应的订单。（疑问：是否删除所有状态的订单）
	 * @param buildingId
	 * @return
	 */
	public boolean deleteRentalOrderByBuilding(Integer buildingId){
		boolean result = false;
		Building building = genericService.load(Building.class, buildingId);
		if (building != null) {
			List<Room> rooms = building.getRooms();
			for (Room room : rooms) {
				RentalOrder orderModel = new RentalOrder();
				orderModel.setRoom(room);
				List<RentalOrder> datas = genericService.searchByModel(orderModel, Condition.DEFAULT).getData();
				if(datas.size()>0){
					for (RentalOrder rentalOrder : datas) {
						genericService.delete(rentalOrder);
						result = true;
					}
				}
			}
		}
		return result;
	}
}
